/**
 * eCommerce Application Sample for J2EE Training 
 * Implementation of CartBean
 * @author Fabienne Boyer - Didier Donsez
 * may 2006
 */

package ecom.beans;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import javax.ejb.Local;
import javax.ejb.SessionSynchronization;
import javax.ejb.Stateful;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.OneToOne;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@Stateful
@Local(CartLocal.class)
public class CartBean implements CartLocal {

	
	@PersistenceContext
	private EntityManager entityManager = null;

	/**
	 * List of the products put into the cart
	 */
	public LinkedHashMap<String, CartProductBean> products = new LinkedHashMap<String, CartProductBean>();

	/**
	 * Sum of the price of every products
	 */
	public float productsPrice = 0;

	/**
	 * price for the delivery
	 */
	public float shippingPrice = 0;

	/**
	 * id of the owner of the cart
	 */
	public CustomerBean customer = null;

	
	
	public CartBean() {
		this(null);
	}
	
	public CartBean(CustomerBean customer) {
		this.customer = customer;
		products = new LinkedHashMap<String, CartProductBean>();
		productsPrice = 0;
		shippingPrice = 0;
	}

	public void setCustomer(CustomerBean customer) {	
		this.customer = customer;
	}
	
	public float getShippingPrice() {
		return this.shippingPrice;
	}

	public float getProductsPrice() {
		return this.productsPrice;
	}
	
	public float getTotalPrice() {
		return this.productsPrice+this.shippingPrice;
	}

	
	
	public List<CartProductBean> listOfProducts() {
		return new LinkedList<CartProductBean>(products.values());
	}

	/**
	 * Carries out the order
	 */
	public boolean ordering() {
		
		Query q = entityManager.createQuery("select ab from AccountBean ab where ab.emailId = ''");
		AccountBean adminAccount = (AccountBean) q.getSingleResult();
		System.err.println(adminAccount.getBalance());
		if (customer == null){
			return false;
		}
		Iterator<CartProductBean> ite = products.values().iterator();
		
		double totalPrice = getTotalPrice(); 
		if (customer.account.getBalance() < totalPrice) {
			return false;
		}

		while (ite.hasNext()){
			CartProductBean cur = ite.next();
			if (cur.product.getStock() < cur.getQuantity()) {
				return false;
			}
		}
		customer.getAccount().withdraw(totalPrice);
		adminAccount.deposit(totalPrice);
				
		ite = products.values().iterator();
		while (ite.hasNext()){
			CartProductBean cur = ite.next();
			cur.product.setStock(cur.product.getStock()-cur.getQuantity());
		}
		
		emptyCart();
		
		return true;
	}

	/**
	 * Adds a product to the cart, and computes the new price and shipping fee
	 * 
	 * @param prod
	 *            The product to add
	 */
	public void putInto(String ref) {
		// If the product is already in the cart, we increment its quantity
		if (products.containsKey(ref)) {
			CartProductBean cpb = products.get(ref);
			cpb.setQuantity(cpb.getQuantity()+1);
		}
		else {
			ProductBean p = entityManager.find(ProductBean.class, ref);
			CartProductBean cpb = new CartProductBean(p,1);
			products.put(cpb.product.getReference(), cpb);
		}
		computePrices();
		//int i = 1;
	}

	public void remove(String ref) {	
		products.remove(ref);
		computePrices();
	}

	public void modifyQuantity(String ref, int newQt) {
		if (products.containsKey(ref)) {
			products.get(ref).setQuantity(newQt);
			computePrices();
		}

	}

	/**
	 * Computes the new prices for this cart (Products' prices and shipping
	 * price)
	 */
	private void computePrices() {
		Iterator<CartProductBean> ite = products.values().iterator();
		productsPrice = 0;
		shippingPrice = 0;

		while (ite.hasNext()) {
			CartProductBean cur = ite.next();
			productsPrice += cur.product.getEuroPrice() * cur.getQuantity();
		}
		// shipping costs 30euros, and is free from 300euros
		if (productsPrice >= 300)
			shippingPrice = 0;
		else
			shippingPrice = 30;
	}

	/**
	 * Resets the cart
	 */
	public void emptyCart() {
		products = new LinkedHashMap<String, CartProductBean>();
		productsPrice = 0;
		shippingPrice = 0;
	}

}
